Skip to content

Stage 5a: Provisioner — deterministic + patterns (v0 critical path)#44

Merged
hanwencheng merged 3 commits intomainfrom
stage-5a
Apr 16, 2026
Merged

Stage 5a: Provisioner — deterministic + patterns (v0 critical path)#44
hanwencheng merged 3 commits intomainfrom
stage-5a

Conversation

@hanwencheng
Copy link
Copy Markdown
Member

@hanwencheng hanwencheng commented Apr 16, 2026

Summary

Ships Stage 5a of agentkeys: the provisioner's deterministic + patterns tier (v0 critical path). agentkeys.provision(service) can now sign up for OpenRouter via a local Playwright script, verify the obtained key against the live API, and store it through the backend. Per the 2026-04-16 CEO review (SELECTIVE EXPANSION), Stage 5b (agentic fallback + audit + script-gen skill) and Stage 6 (npm packaging) are explicitly deferred to v0.1.

  • 15/15 PRD user stories PASSED — see .omc/prd.json
  • 82 tests passing (67 Rust across 4 crates + 15 TypeScript)
  • Architect review: CONDITIONAL_APPROVAL (Opus tier, 4 non-blocking follow-ups routed to Stage 5b, see progress.txt)
  • harness/stage-5a-done.sh exits 0 with "STAGE 5a PASSED"
  • Rebased onto main cleancrates/agentkeys-core/src/session_store.rs is not part of this PR (no delta from main)

What shipped

Rust (4 crates)

  • agentkeys-types::ProvisionEvent + TripwireKind + ProvisionErrorCode — shared schema for Rust↔TS IPC (tagged unions, snake_case)
  • agentkeys-provisioner (new crate): Provisioner RAII mutex with PROVISION_IN_PROGRESS sentinel, spawn_and_collect subprocess driver with line-delimited JSON IPC + 120s timeout + malformed-line abort, run_provision orchestrator (verify→store gate), mask_key helper, structured metrics emitter
  • agentkeys-mcp::agentkeys.provision tool registered with {service, force?} schema, structured error code mapping
  • agentkeys-cli::provision <service> [--force] subcommand with masked-key stdout + CLAUDE.md-format error output

TypeScript workspace (new: provisioner-scripts/)

  • src/types.ts — exact mirror of Rust ProvisionEvent (typed boundary, no opaque parsing)
  • src/lib/email.ts — Gmail plus-addressing IMAP via imapflow + structured timeout
  • src/lib/verify.ts — per-service verification (openrouter → GET /api/v1/models, Bearer auth); returns phantom / endpoint_down / rate_limited distinctions
  • src/patterns/signup_email_otp.ts — reusable pattern, zero service-specific strings (grep-enforced)
  • src/scrapers/openrouter.ts — composes the pattern + calls verify before emitting Success
  • tests/fixtures/openrouter/ — HAR-equivalent hermetic fixtures served via page.route() + route.fulfill()
  • tests/scrapers/openrouter.phantom.test.ts — chaos test proving the verification gate catches a sk-or-v1-FAKE decoy key

Harness

  • harness/stage-5a-done.sh — 4-gate verifier (cargo tests, npm tests, grep guard against service strings in patterns/, isolated phantom chaos)
  • harness/features.json + harness/progress.json updated

Design artifacts (earlier turns this session)

  • docs/spec/plans/development-stages.md restructured: Stage 5 → 5a/5b split, Stage 6 deferred, eng-review + design-review decisions locked as implementation notes
  • TODOS.md added (Twitter deferred, Phase C scraper target list)
  • ~/.claude/skills/agentkeys-record-scraper/SKILL.md (global, not in this PR) — dev-time tool for adding future scrapers

Architectural constraints enforced

  • Typed parameters at Rust↔TS boundary; Rust ProvisionEvent enum + TS discriminated union share the exact same JSON shape
  • Patterns contain zero service-specific strings (grep -iE "openrouter\|brave\|jina\|groq\|anthropic\|gemini" provisioner-scripts/src/patterns/ returns empty)
  • Every scraper success path calls verify() before emitting Success; phantom chaos test proves the gate
  • HAR-equivalent fixture-based hermetic tests; zero live-site calls in the test suite
  • Pattern extraction regression seam: the same fixture test passed both before AND after extracting signup_email_otp from the inline OpenRouter scraper

Stage 5b follow-ups (architect review, non-blocking)

Logged in progress.txt for Stage 5b:

  1. re_verify_existing is a placeholder returning true — real re-verification needed
  2. CLI does not stream ProvisionEvent::Progress events to stderr in real time (single-shot today)
  3. Phantom chaos emits code: "store_failed" — should be a dedicated ProvisionErrorCode::VerificationFailed variant
  4. HAR fixtures are hand-crafted HTML (functionally equivalent, documented) — optional normalization to .har

Optimality suggestions also captured for Stage 5b: streaming orchestrator API, consolidate service-dispatch, NoopBackend extraction, exhaustive event_to_error match.

Scope explicitly NOT in this PR

  • Stage 5b: agentic fallback via MCP browser primitives, fallback audit trail, fallback→PR loop, LLM script-generator dev tool usage, 4 additional patterns (OAuth-Google/GitHub, magic-link, password+email-verify)
  • Stage 6: npm package, install.sh, README polish
  • Stage 8: production hardening
  • Additional scrapers beyond OpenRouter — Brave Search, Jina Search, Anthropic, Groq, Gemini come via /agentkeys-record-scraper skill after this merges (per TODOS.md Phase C list). Twitter deferred to TODOs, Instagram dropped.

Test plan

  • bash harness/stage-5a-done.sh exits 0
  • cargo test -p agentkeys-types -p agentkeys-provisioner -p agentkeys-mcp -p agentkeys-cli passes (67 tests)
  • npm install --prefix provisioner-scripts && npm test --prefix provisioner-scripts passes (15 tests)
  • grep -iE "openrouter|brave|jina|groq|anthropic|gemini|twitter|instagram" provisioner-scripts/src/patterns/ returns empty
  • Phantom chaos test catches a fake-shaped key: cd provisioner-scripts && npx vitest run tests/scrapers/openrouter.phantom.test.ts
  • (Manual, requires real Gmail + OpenRouter ToS check) Live provision end-to-end — deferred until ToS clarity per TODOS.md

Reviews already run (2026-04-16)

  • /plan-ceo-review — SELECTIVE EXPANSION, 7 proposals, 5 accepted, 1 deferred, 1 rejected; 1 critical gap caught (silent-corrupt-credential → mandatory verification fix) — CEO plan at ~/.gstack/projects/litentry-agentKeys/ceo-plans/2026-04-16-stage-5-hybrid-agentic.md
  • /plan-eng-review — 3 P1 decisions locked (IPC schema, concurrency, MCP scope), 5 implementation notes baked into plan, 11 additional tests added to story tables — test plan at ~/.gstack/projects/litentry-agentKeys/*eng-review-test-plan*.md
  • /plan-design-review — 4 UX decisions locked (masked-key output, stderr progress, atty TTY detection, duplicate-provision verify-and-report); score 5→9/10
  • Ralph architect review — CONDITIONAL_APPROVAL with 4 non-blocking Stage 5b follow-ups

🤖 Generated with Claude Code

…crate (types + mutex concurrency + subprocess IPC)
@hanwencheng hanwencheng force-pushed the stage-5a branch 2 times, most recently from b929532 to 38c41be Compare April 16, 2026 15:45
@hanwencheng hanwencheng merged commit 34cbe45 into main Apr 16, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant